package com.kimehwa.studyboot.utils;

/**
 * @author xiaodongguan
 * @description
 * @since 2021-07-26 14:10
 */


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.kimehwa.studyboot.bean.Couple;
import com.kimehwa.studyboot.bean.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

final class JsonUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);

    private static ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
            .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true).configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);


    private static ObjectMapper noAnnoMapper = new ObjectMapper().disable(MapperFeature.USE_ANNOTATIONS)
            .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true).configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    ;

    private JsonUtil() {
    }

    /**
     * Object可以是POJO，也可以是Collection或数组。 如果对象为Null, 返回"null". 如果集合为空集合, 返回"[]".
     */
    public static String toJson(Object object) throws JsonProcessingException {
        return mapper.writeValueAsString(object);
    }

    public static String toJsonWithoutException(Object object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            LOGGER.error("object to json error, ", e);
        }
        return null;
    }

    /**
     * 作用同{@link #toJson(Object)}, 此方法会忽略注解.
     */
    public static String toJsonIgnoreAnno(Object object) throws JsonProcessingException {
        return noAnnoMapper.writeValueAsString(object);
    }

    /**
     * 将对象转化为Json字节数组.
     */
    public static byte[] toJsonByteArray(Object object) throws JsonProcessingException {
        return mapper.writeValueAsBytes(object);
    }

    /**
     * 将对象转化为Json字节数组. 忽略注解.
     */
    public static byte[] toJsonByteArrayIgnoreAnno(Object object) throws JsonProcessingException {
        return noAnnoMapper.writeValueAsBytes(object);
    }

    /**
     * 反序列化POJO或简单Collection如{@code List<String>}.
     *
     * <p>如果JSON字符串为Null或"null"字符串, 返回Null. 如果JSON字符串为"[]", 返回空集合.<br>
     * 如需反序列化复杂Collection如{@code List<Object>}, 请使用fromJson(String, JavaType).<br>
     *
     * @see #fromJson(String, JavaType)
     */
    public static <T> T fromJson(String jsonString, Class<T> clazz) throws IOException {
        return mapper.readValue(jsonString, clazz);
    }

    /**
     * 流转换为对象.
     *
     * @param contentStream 数据流.
     * @param clazz         转换类型.
     * @param <T>           转换类型.
     * @return 目标对象.
     */
    public static <T> T fromJson(InputStream contentStream, Class<T> clazz) throws IOException {
        if (contentStream == null) {
            return null;
        }
        return mapper.readValue(contentStream, clazz);
    }

    /**
     * 反序列化复杂Collection如{@code List<Bean>}, 先使用createCollectionType()或constructMapType()构造类型, 然后调用本函数.
     */
    public static <T> T fromJson(String jsonString, JavaType javaType) throws IOException {
        return (T) mapper.readValue(jsonString, javaType);
    }

    /**
     * 构造Collection类型.
     */
    public static <T extends Collection> T constructCollectionType(String jsonString, Class<? extends Collection> collectionClass, Class<?> elementClass) throws IOException {
        return mapper.readValue(jsonString,
                mapper.getTypeFactory().constructCollectionType(collectionClass, elementClass));
    }

    /**
     * 构造Map类型.
     */
    public static <T extends Map> T constructMapType(String jsonString, Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) throws IOException {
        return mapper.readValue(jsonString,
                mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass));
    }

    /**
     * 构造数组类型.
     */
    public static Object[] constructArrayType(String jsonString, Class<?> elementClass) throws IOException {
        return mapper.readValue(jsonString,
                mapper.getTypeFactory().constructArrayType(elementClass));
    }

    /**
     * 当JSON里只含有Bean的部分属性时，更新一个已存在Bean，只覆盖该部分的属性.
     */
    public static void update(String jsonString, Object object) throws IOException {
        mapper.readerForUpdating(object).readValue(jsonString);
    }


    public static void main(String[] args) throws IOException {
//        Couple guan = new Couple(3, "guan");
//        byte[] s = JsonUtil.toJsonByteArray(guan); // 转化为一个byte流
//        for(byte s1 :s){
//            System.out.println(s1);
//        }
////        Couple couple = JsonUtil.fromJson(s, Couple.class);
        UserPar guan = new UserPar(1, "guan");
        UserChi userChi = new UserChi();
        BeanUtils.copyProperties(guan,userChi); // 这个方法挺好用
        System.out.println(userChi);
    }
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class UserPar{
        private int id;
        private String name;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class UserChi{
        private Integer id;
        private String name;
        private Integer age;
    }

}

